package com.eatme.web.security.authentication.phonecode.filter;

import com.eatme.web.security.authentication.phonecode.authentication.PhoneCodeAuthenticationToken;
import com.eatme.web.security.authentication.phonecode.vo.PhoneCodeRequest;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;

public class PhoneCodeAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

    private static final Logger LOG = LoggerFactory.getLogger(PhoneCodeAuthenticationFilter.class);

    private final ObjectMapper objectMapper;

    /**
     * 前端传来的 参数名 - 用于request.getParameter 获取
     */
    private final String DEFAULT_EMAIL_NAME="phone";

    private final String DEFAULT_EMAIL_CODE="code";

    /**
     * 是否 仅仅post方式
     */
    private boolean postOnly = true;

    /**
     * 通过 传入的 参数 创建 匹配器
     * 即 Filter过滤的url
     */
    public PhoneCodeAuthenticationFilter(ObjectMapper objectMapper) {
        super(new AntPathRequestMatcher("/phone/login"));
        this.objectMapper = objectMapper;
    }

    /**
     * filter 获得 用户名（邮箱） 和 密码（验证码） 装配到 token 上 ，
     * 然后把token 交给 provider 进行授权
     */
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {

//        if(postOnly && !request.getMethod().equals("POST") ){
//            throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
//        }else{
//            String email = getEmail(request);
//            if(email == null){
//                email = "";
//            }
//            email = email.trim();
//            //如果 验证码不相等 故意让token出错 然后走springsecurity 错误的流程
//            boolean flag = checkCode(request);
//            //封装 token
//            EmailCodeAuthenticationToken token = new EmailCodeAuthenticationToken(email,new ArrayList<>());
//            this.setDetails(request,token);
//            //交给 manager 发证
//            return this.getAuthenticationManager().authenticate(token);
//        }


        PhoneCodeAuthenticationToken authenticationToken;
        if (postOnly && !request.getMethod().equals("POST")) {
            throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
        }
        try (InputStream is = request.getInputStream()) {
            //  在这里取消原有的通过 request parameter 形式获取用户名密码的方法, 替换为 json 数据格式的获取
            PhoneCodeRequest authenticationBean = objectMapper.readValue(is, PhoneCodeRequest.class);

            authenticationToken = new PhoneCodeAuthenticationToken(authenticationBean.getPhone(),authenticationBean.getCode(),new ArrayList<>());
        } catch (IOException e) {
            throw new BadCredentialsException("没有找到用户名或密码参数");
        }
        // Allow subclasses to set the "details" property
        setDetails(request, authenticationToken);
        return this.getAuthenticationManager().authenticate(authenticationToken);



    }

    /**
     * 获取 头部信息 让合适的provider 来验证他
     */
    public void setDetails(HttpServletRequest request , PhoneCodeAuthenticationToken token ){
        token.setDetails(this.authenticationDetailsSource.buildDetails(request));
    }

    /**
     * 获取 传来 的Email信息
     */
    public String getEmail(HttpServletRequest request ){
        String result=  request.getParameter(DEFAULT_EMAIL_NAME);
        return result;
    }

    /**
     * 判断 传来的 验证码信息 以及 session 中的验证码信息
     */
    public boolean checkCode(HttpServletRequest request ){
        String code = request.getParameter(DEFAULT_EMAIL_CODE);
        LOG.info("code**********{}",code);
        // TODO 另外再写一个链接 生成 验证码 那个验证码 在生成的时候  存进redis 中去
        //TODO  这里的验证码 写在Redis中， 到时候取出来判断即可 验证之后 删除验证码
        if(code.equals("123456")){
            return true;
        }
        return false;
    }


}